package org.hepeng.compression.test;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.ByteArrayCodec;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.codec.LZ4Codec;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author he peng
 * @date 2021/10/9
 */

@RestController
@AllArgsConstructor
@Slf4j
public class Controller {

    final RedissonClient redissonClient;

    final String CACHE_REGION_NAME = "COMPRESSION_DATA_CACHE_TEST";

    final LZ4Factory lz4Factory = LZ4Factory.fastestInstance();


    @PostMapping("/non-compression-write")
    public Map<String , Object> nonCompressionWrite(@RequestParam String str , @RequestParam Integer loop) {

        RMapCache<Object, Object> mapCache = redissonClient.getMapCache(CACHE_REGION_NAME , new StringCodec());
        mapCache.clear();

        long sTime = System.nanoTime();

        for (int i = 0 ; i < loop; i++) {
            mapCache.put(i , str);
        }

        long eTime = System.nanoTime();

        Map<String , Object> payload = new HashMap<>();
        payload.put("loop" , loop);
        payload.put("time" , TimeUnit.NANOSECONDS.toMillis(eTime - sTime));

        return payload;
    }

    @PostMapping("/lz4-compression-write")
    public Map<String , Object> lz4CompressionWrite(@RequestParam String str , @RequestParam Integer loop) {

        RMapCache<Object, Object> mapCache = redissonClient.getMapCache(CACHE_REGION_NAME , new LZ4Codec(new JsonJacksonCodec()));
        mapCache.clear();

        LZ4Compressor compressor = lz4Factory.fastCompressor();

        long sTime = System.nanoTime();

        int decompressedLength = 0;
        int compressedLength = 0;
        for (int i = 0 ; i < loop; i++) {
            // compression

//            byte[] data = str.getBytes(StandardCharsets.UTF_8);
//            decompressedLength = data.length;
//            int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
//            byte[] compressed = new byte[maxCompressedLength];
//            compressedLength = compressor.compress(data, 0, decompressedLength, compressed, 0, maxCompressedLength);

            mapCache.put(i , str);
        }

        long eTime = System.nanoTime();

        Map<String , Object> payload = new HashMap<>();
        payload.put("loop" , loop);
        payload.put("time" , TimeUnit.NANOSECONDS.toMillis(eTime - sTime));
        payload.put("decompressedLength" , decompressedLength);
        payload.put("compressedLength" , compressedLength);

        return payload;
    }

    @GetMapping("/lz4-decompress-read")
    public List<Object> lz4DecompressRead(Integer loop) {

        RMapCache<Object, Object> mapCache = redissonClient.getMapCache(CACHE_REGION_NAME , new LZ4Codec(new JsonJacksonCodec()));

        List<Object> list = new ArrayList<>();

        long sTime = System.nanoTime();

        for (int i = 0 ; i < loop; i++) {

            Object val = mapCache.get(i);
            list.add(val);
        }

        long eTime = System.nanoTime();

        log.info("lz4-decompress-read time {} ms " , TimeUnit.NANOSECONDS.toMillis(eTime - sTime));
        return list;
    }
}
